package com.ruoyi.system.service.impl;

import java.util.List;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.system.mapper.ApplicationMapper;
import com.ruoyi.system.mapper.TopicMapper;
import com.ruoyi.system.mapper.TeacherInfoMapper;
import com.ruoyi.system.domain.Application;
import com.ruoyi.system.domain.Topic;
import com.ruoyi.system.service.IApplicationService;
import com.ruoyi.common.exception.ServiceException;

/**
 * 志愿申请Service业务层处理
 *
 * @author ltr
 * @date 2024-10-23
 */
@Service
public class ApplicationServiceImpl implements IApplicationService
{
    @Autowired
    private ApplicationMapper applicationMapper;

    @Autowired
    private TopicMapper topicMapper;

    @Autowired
    private TeacherInfoMapper teacherInfoMapper;

    /**
     * 查询志愿申请
     *
     * @param applicationId 志愿申请主键
     * @return 志愿申请
     */
    @Override
    public Application selectApplicationByApplicationId(Long applicationId)
    {
        return applicationMapper.selectApplicationByApplicationId(applicationId);
    }

    /**
     * 查询志愿申请列表（管理员使用）
     *
     * @param application 志愿申请
     * @return 志愿申请
     */
    @Override
    public List<Application> selectApplicationList(Application application)
    {
        return applicationMapper.selectApplicationList(application);
    }

    /**
     * 查询学生的志愿申请列表
     *
     * @param studentId 学生ID
     * @return 志愿申请集合
     */
    @Override
    public List<Application> selectApplicationListByStudentId(Long studentId)
    {
        return applicationMapper.selectApplicationListByStudentId(studentId);
    }

    /**
     * 查询教师的题目下的申请列表
     *
     * @param teacherId 教师ID
     * @return 志愿申请集合
     */
    @Override
    public List<Application> selectApplicationListByTeacherId(Long teacherId)
    {
        return applicationMapper.selectApplicationListByTeacherId(teacherId);
    }

    /**
     * 查询指定题目的申请列表
     *
     * @param topicId 题目ID
     * @return 志愿申请集合
     */
    @Override
    public List<Application> selectApplicationListByTopicId(Long topicId)
    {
        return applicationMapper.selectApplicationListByTopicId(topicId);
    }

    /**
     * 查询教师已录取的学生列表
     *
     * @param teacherId 教师ID
     * @return 志愿申请集合
     */
    @Override
    public List<Application> selectAcceptedStudentsByTeacherId(Long teacherId)
    {
        return applicationMapper.selectAcceptedStudentsByTeacherId(teacherId);
    }

    /**
     * 学生申请志愿
     *
     * @param application 志愿申请
     * @return 结果
     */
    @Override
    @Transactional
    public int applyForTopic(Application application)
    {
        // 1. 检查学生是否已被录取
        Application accepted = applicationMapper.selectAcceptedApplicationByStudentId(application.getStudentId());
        if (accepted != null)
        {
            throw new ServiceException("您已被录取，无法再申请其他志愿");
        }

        // 2. 检查该优先级志愿是否已满
        int count = applicationMapper.countStudentApplicationsByPriority(
                application.getStudentId(), application.getPriority());
        if (count > 0)
        {
            throw new ServiceException("该志愿优先级已有申请，请先取消后再申请");
        }

        // 3. 检查是否重复申请同一题目
        int existed = applicationMapper.checkStudentApplied(
                application.getStudentId(), application.getTopicId());
        if (existed > 0)
        {
            throw new ServiceException("您已申请过该题目");
        }

        // 4. 检查题目是否存在
        Topic topic = topicMapper.selectTopicByTopicId(application.getTopicId());
        if (topic == null)
        {
            throw new ServiceException("题目不存在");
        }

        // 5. 检查题目是否已满
        if (topic.getCurrentStudents() >= topic.getMaxStudents())
        {
            throw new ServiceException("该题目名额已满");
        }

        // 6. 检查题目状态是否开放
        if (!"开放".equals(topic.getStatus()))
        {
            throw new ServiceException("该题目当前不开放申请");
        }

        // 7. 直接插入新的申请记录（保留历史记录）
        application.setStatus("待审核");
        application.setCreateTime(DateUtils.getNowDate());

        return applicationMapper.insertApplication(application);

    }

    /**
     * 学生取消志愿申请
     *
     * @param applicationId 申请ID
     * @param studentId 学生ID
     * @return 结果
     */
    @Override
    public int cancelApplication(Long applicationId, Long studentId)
    {
        // 1. 检查申请是否属于该学生
        if (applicationMapper.checkApplicationOwner(applicationId, studentId) == 0)
        {
            throw new ServiceException("无权取消该申请");
        }

        // 2. 检查申请状态是否可以取消
        Application application = applicationMapper.selectApplicationByApplicationId(applicationId);
        if (application == null)
        {
            throw new ServiceException("申请不存在");
        }
        if (!"待审核".equals(application.getStatus()))
        {
            throw new ServiceException("该申请当前状态无法取消");
        }

        // 3. 更新状态为已取消
        return applicationMapper.updateApplicationStatus(applicationId, "已取消");
    }

    /**
     * 教师录取学生
     *
     * @param applicationId 申请ID
     * @param teacherId 教师ID
     * @param reviewBy 审核人
     * @return 结果
     */
    @Override
    @Transactional
    public int acceptStudent(Long applicationId, Long teacherId, String reviewBy)
    {
        // 1. 检查申请是否属于该教师的题目
        if (applicationMapper.checkApplicationBelongsToTeacher(applicationId, teacherId) == 0)
        {
            throw new ServiceException("无权审核该申请");
        }

        // 2. 检查申请状态
        Application application = applicationMapper.selectApplicationByApplicationId(applicationId);
        if (application == null)
        {
            throw new ServiceException("申请不存在");
        }
        if (!"待审核".equals(application.getStatus()))
        {
            throw new ServiceException("该申请已被处理");
        }

        // 3. 检查学生是否已被其他题目录取
        Application accepted = applicationMapper.selectAcceptedApplicationByStudentId(application.getStudentId());
        if (accepted != null)
        {
            throw new ServiceException("该学生已被其他题目录取");
        }

        // 4. 检查题目是否还有名额
        Topic topic = topicMapper.selectTopicByTopicId(application.getTopicId());
        if (topic == null)
        {
            throw new ServiceException("题目不存在");
        }
        if (topic.getCurrentStudents() >= topic.getMaxStudents())
        {
            throw new ServiceException("题目名额已满");
        }

        // 5. 录取该学生
        int result = applicationMapper.acceptApplication(applicationId, reviewBy);
        if (result > 0)
        {
            // 6. 将该学生的其他志愿设置为已失效
            applicationMapper.invalidateOtherApplications(application.getStudentId(), applicationId);

            // 7. 更新题目的当前学生数 +1
            topicMapper.updateTopicCurrentStudents(application.getTopicId(), 1);

            // 7.5. 更新教师的当前指导学生数 +1
            teacherInfoMapper.updateTeacherCurrentStudents(topic.getTeacherId(), 1);

            // 8. 如果题目已满，更新题目状态为已满
            Topic updatedTopic = topicMapper.selectTopicByTopicId(application.getTopicId());
            if (updatedTopic.getCurrentStudents() >= updatedTopic.getMaxStudents())
            {
                updatedTopic.setStatus("已满");
                topicMapper.updateTopic(updatedTopic);
            }
        }

        return result;
    }

    /**
     * 教师拒绝学生
     *
     * @param applicationId 申请ID
     * @param teacherId 教师ID
     * @param reviewReason 拒绝理由
     * @param reviewBy 审核人
     * @return 结果
     */
    @Override
    public int rejectStudent(Long applicationId, Long teacherId, String reviewReason, String reviewBy)
    {
        // 1. 检查申请是否属于该教师的题目
        if (applicationMapper.checkApplicationBelongsToTeacher(applicationId, teacherId) == 0)
        {
            throw new ServiceException("无权审核该申请");
        }

        // 2. 检查申请状态
        Application application = applicationMapper.selectApplicationByApplicationId(applicationId);
        if (application == null)
        {
            throw new ServiceException("申请不存在");
        }
        if (!"待审核".equals(application.getStatus()))
        {
            throw new ServiceException("该申请已被处理");
        }

        // 3. 拒绝理由必填
        if (reviewReason == null || reviewReason.trim().isEmpty())
        {
            throw new ServiceException("请填写拒绝理由");
        }

        // 4. 拒绝该学生
        return applicationMapper.rejectApplication(applicationId, reviewReason, reviewBy);
    }

    /**
     * 批量删除志愿申请（管理员）
     *
     * @param applicationIds 需要删除的志愿申请主键
     * @return 结果
     */
    @Override
    public int deleteApplicationByApplicationIds(Long[] applicationIds)
    {
        return applicationMapper.deleteApplicationByApplicationIds(applicationIds);
    }

    /**
     * 删除志愿申请信息（管理员）
     *
     * @param applicationId 志愿申请主键
     * @return 结果
     */
    @Override
    public int deleteApplicationByApplicationId(Long applicationId)
    {
        return applicationMapper.deleteApplicationByApplicationId(applicationId);
    }

    /**
     * 检查学生是否可以申请（未被录取且该志愿优先级未满）
     *
     * @param studentId 学生ID
     * @param priority 优先级
     * @return 是否可以申请
     */
    @Override
    public boolean canStudentApply(Long studentId, Integer priority)
    {
        // 检查是否已被录取
        Application accepted = applicationMapper.selectAcceptedApplicationByStudentId(studentId);
        if (accepted != null)
        {
            return false;
        }

        // 检查该优先级是否已有申请
        int count = applicationMapper.countStudentApplicationsByPriority(studentId, priority);
        return count == 0;
    }

    /**
     * 检查题目是否还有名额
     *
     * @param topicId 题目ID
     * @return 是否有名额
     */
    @Override
    public boolean isTopicAvailable(Long topicId)
    {
        Topic topic = topicMapper.selectTopicByTopicId(topicId);
        if (topic == null)
        {
            return false;
        }
        return topic.getCurrentStudents() < topic.getMaxStudents() && "开放".equals(topic.getStatus());
    }

    /**
     * 检查申请是否属于指定学生
     *
     * @param applicationId 申请ID
     * @param studentId 学生ID
     * @return 是否拥有
     */
    @Override
    public boolean checkApplicationOwner(Long applicationId, Long studentId)
    {
        return applicationMapper.checkApplicationOwner(applicationId, studentId) > 0;
    }

    /**
     * 检查申请是否属于指定教师的题目
     *
     * @param applicationId 申请ID
     * @param teacherId 教师ID
     * @return 是否属于
     */
    @Override
    public boolean checkApplicationBelongsToTeacher(Long applicationId, Long teacherId)
    {
        return applicationMapper.checkApplicationBelongsToTeacher(applicationId, teacherId) > 0;
    }
}